#ifndef _HAL_TCPC_OPERATION_H_
#define _HAL_TCPC_OPERATION_H_

#include "typec_pd_config.h"

#define BITS_PER_LONG                       32
#define BIT(bit)                            ((uint32_t)1 << (bit))
#define GENMASK(h, l)                       (((~0UL) << (l)) & \
                                             (~0UL >> (BITS_PER_LONG - 1 - (h))))

/* TCPCI Spec standard */
#define TCPC_REG_VID                        (0x00)
#define TCPC_REG_PID                        (0x02)
#define TCPC_REG_DID                        (0x04)
#define TCPC_REG_TYPEC_REV                  (0x06)
#define TCPC_REG_PD_REV                     (0x08)
#define TCPC_REG_PDIF_REV                   (0x0A)

#define TCPC_REG_ALERT                      (0x10)
#define TCPC_REG_ALERT_MASK                 (0x12)
#define TCPC_REG_POWER_STATUS_MASK          (0x14)
#define TCPC_REG_FAULT_STATUS_MASK          (0x15)
#define TCPC_REG_EXT_STATUS_MASK            (0x16)

#define TCPC_REG_TCPC_CTRL                  (0x19)
#define TCPC_REG_ROLE_CTRL                  (0x1A)
#define TCPC_REG_FAULT_CTRL                 (0x1B)
#define TCPC_REG_POWER_CTRL                 (0x1C)

#define TCPC_REG_CC_STATUS                  (0x1D)
#define TCPC_REG_POWER_STATUS               (0x1E)
#define TCPC_REG_FAULT_STATUS               (0x1F)
#define TCPC_REG_EXT_STATUS                 (0x20)

#define TCPC_REG_COMMAND                    (0x23)

#define TCPC_REG_MSG_HDR_INFO               (0x2e)

#define TCPC_REG_RX_DETECT                  (0x2f)

#define TCPC_REG_RX_BYTE_CNT                (0x30)
#define TCPC_REG_RX_BUF_FRAME_TYPE          (0x31)
#define TCPC_REG_RX_HDR                     (0x32)
#define TCPC_REG_RX_DATA                    (0x34)

#define TCPC_REG_TRANSMIT                   (0x50)
#define TCPC_REG_TX_BYTE_CNT                (0x51)
#define TCPC_REG_TX_HDR                     (0x52)
#define TCPC_REG_TX_DATA                    (0x54)

/* SGM MICRO specific */
#define SGMICRO_CTRL1                       (0x90)
#define SGMICRO_VCONN_OCP                   (0x93)
#define SGMICRO_STATUS                      (0x97)
#define SGMICRO_INT                         (0x98)
#define SGMICRO_INT_MASK                    (0x99)
#define SGMICRO_CTRL2                       (0x9B)
#define SGMICRO_REG_SWRESET                 (0xA0)
#define SGMICRO_REG_DRP_TOGGLE_CYCLE        (0xA2)
#define SGMICRO_REG_DRP_DUTY_CTRL0          (0xA3)
#define SGMICRO_REG_DRP_DUTY_CTRL1          (0xA4)
#define SGMICRO_REG_WDT                     (0xA5)

/* TCPC_REG_ALERT & TCPC_REG_ALERT_MASK */
#define TCPC_ALERT_VENDOR_VSAFE0V           (1 << 17)
#define TCPC_ALERT_VENDOR_DEFINED           (1 << 15)
#define TCPC_ALERT_EXTENDED_STATUS          (1 << 13)
#define TCPC_ALERT_RX_OVERFLOW              (1 << 10)
#define TCPC_ALERT_FAULT                    (1 << 9)
#define TCPC_ALERT_TX_SUCCESS               (1 << 6)
#define TCPC_ALERT_TX_DISCARDED             (1 << 5)
#define TCPC_ALERT_TX_FAILED                (1 << 4)
#define TCPC_ALERT_RX_HARD_RST              (1 << 3)
#define TCPC_ALERT_RX_STATUS                (1 << 2)
#define TCPC_ALERT_POWER_STATUS             (1 << 1)
#define TCPC_ALERT_CC_STATUS                (1 << 0)

/* TCPC_REG_POWER_STATUS & TCPC_REG_POWER_STATUS_MASK */
#define TCPC_POWER_STATUS_TCPC_INITIAL      (1 << 6)
#define TCPC_POWER_STATUS_VBUS_PRES         (1 << 2)
#define TCPC_POWER_STATUS_VCONN_PRES        (1 << 1)

/* TCPC_REG_FAULT_STATUS & TCPC_REG_FAULT_STATUS_MASK */
#define TCPC_FAULT_STATUS_VCONN_OC          (1 << 1)
#define TCPC_FAULT_STATUS_I2C_ERROR         (1 << 0)

/* TCPC_REG_ROLE_CTRL */
#define TCPC_ROLE_CTRL_DRP                  (1 << 6)
#define TCPC_ROLE_CTRL_RP_VALUE             GENMASK(5, 4)
    #define TCPC_ROLE_CTRL_RP_DEFAULT       0
    #define TCPC_ROLE_CTRL_RP_1A5           1
    #define TCPC_ROLE_CTRL_RP_3A            2
#define TCPC_ROLE_CTRL_CC2                  GENMASK(3, 2)
#define TCPC_ROLE_CTRL_CC2_SHIFT            2
#define TCPC_ROLE_CTRL_CC1                  GENMASK(1, 0)
#define TCPC_ROLE_CTRL_CC1_SHIFT            0
    #define TCPC_ROLE_CTRL_CC_RA            0
    #define TCPC_ROLE_CTRL_CC_RP            1
    #define TCPC_ROLE_CTRL_CC_RD            2
    #define TCPC_ROLE_CTRL_CC_OPEN          3
#define TCPC_ROLE_CTRL_SET(drp, rp, cc1, cc2)   \
        (((drp) << 6) | ((rp) << 4) | ((cc2) << 2) | (cc1))

/* TCPC_REG_TCPC_CTRL */
#define TCPC_TCPC_CTRL_BIST_TEST_MODE       (1 << 1)
#define TCPC_TCPC_CTRL_PLUG_ORIENT          (1 << 0)

/* TCPC_REG_POWER_CTRL */
#define TCPC_POWER_CTRL_EN_VCONN            (1 << 0)

/* TCPC_REG_CC_STATUS */
#define TCPC_CC_STATUS_LOOKING4CONN         (1 << 5)
#define TCPC_CC_STATUS_CONNRESULT           (1 << 4)
#define TCPC_CC_STATUS_CC2                  GENMASK(3, 2)
#define TCPC_CC_STATUS_CC2_SHIFT            2
#define TCPC_CC_STATUS_CC1                  GENMASK(1, 0)
#define TCPC_CC_STATUS_CC1_SHIFT            0

/* TCPC_REG_COMMAND */
#define TCPC_COMMAND_ENABLE_VBUS_DETECT     0x33
#define TCPC_COMMAND_LOOK4CONNECTION        0x99

/* TCPC_REG_MSG_HDR_INFO */
#define TCPC_MSG_HDR_INFO_SET(sop, rev, dr, pr) \
        (((sop) << 4) | ((rev) << 1) | ((dr) << 3) | (pr))

/* TCPC_REG_RX_DETECT */
#define TCPC_RX_DETECT_CABLE_RESET          (1 << 6)
#define TCPC_RX_DETECT_HARD_RESET           (1 << 5)
#define TCPC_RX_DETECT_DBG_PP               (1 << 4)
#define TCPC_RX_DETECT_DBG_P                (1 << 3)
#define TCPC_RX_DETECT_SOP_PP               (1 << 2)
#define TCPC_RX_DETECT_SOP_P                (1 << 1)
#define TCPC_RX_DETECT_SOP                  (1 << 0)

/* TCPC_REG_RX_BYTE_CNT */
#define TCPC_RECEIVED_SOP_MESSAGE           GENMASK(2, 0)

/* TCPC_REG_TRANSMIT */
#define TCPC_TRANSMIT_SET(retry, type)      (((retry) << 4) | (type))

/* SGMICRO_STATUS */
#define SGMICRO_VSAFE0V                     (1 << 1)

/* SGMICRO_INT & SGMICRO_INT_MASK */
#define SGMICRO_INT_RA_DETACH               (1 << 5)
#define SGMICRO_INT_CC_OVP                  (1 << 2)
#define SGMICRO_INT_VSAFE0V                 (1 << 1)
#define SGMICRO_INT_WAKEUP                  (1 << 0)

/* SGMICRO_CTRL2 */
#define SGMICRO_CK_300K_SEL                 (1 << 7)
#define SGMICRO_SHUTDOWN_OFF                (1 << 5)
#define SGMICRO_ENEXTMSG                    (1 << 4)
#define SGMICRO_AUTOIDLE_EN                 (1 << 3)
#define SGMICRO_AUTOIDLE_TIMEOUT            GENMASK(2, 0)

/* SGMICRO_REG_SWRESET */
#define SGMICRO_SOFT_RESET                  (1 << 0)

#pragma pack(push, 1)
struct tcpc_transmit_data {
    uint8_t cnt;
    uint16_t msg_header;
    uint8_t data[28];
};
#pragma pack(pop)

/* API */
int charger_hw_init(void);
int charger_set_iindpm(uint16_t ma);
int charger_set_otg_ilmt(uint16_t ma);
int charger_set_hiz(bool enable);
int charger_vbus_control(bool enable);
int charger_vbus_discharge(bool enable);
int tcpc_command(uint8_t cmd);
int tcpc_software_reset(void);
int tcpc_get_vbus_status(uint8_t *vbus);
int tcpc_get_cc_status(uint8_t *cc1, uint8_t *cc2);
int tcpc_get_alert_status(uint32_t *alert_sts);
int tcpc_get_tx_result(uint8_t *tx_sts);
int tcpc_alert_status_clear(uint32_t mask);
int tcpc_start_drp_toggle(void);
int tcpc_set_local_rp_level(uint8_t cc);
int tcpc_set_cc(uint8_t cc1, uint8_t cc2);
int tcpc_set_orient(uint8_t polarity);
int tcpc_set_vconn(bool enable);
int tcpc_get_remote_rplvl(uint8_t *rp_level, uint8_t polarity);
int tcpc_get_rx_message(uint8_t *frame_type, uint16_t *msg_hdr, uint32_t *payload);
int tcpc_transmit(uint8_t frame_type, uint16_t header, uint8_t retry, const uint32_t *data);
int tcpc_set_bist_test_mode(bool enable);
int tcpc_set_rx_enable(uint8_t enable);
int tcpc_set_msg_header(uint8_t power_role, uint8_t data_role);
int tcpc_hw_init(struct typec_port_info *port_info);

void dump_tcpc_registers(void);

#endif
